<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\WorkContact\Action\Dashboard;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\Utils\Codec\Json;
use MoChat\App\Common\Middleware\DashboardAuthMiddleware;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\Rbac\Middleware\PermissionMiddleware;
use MoChat\App\WorkContact\Constants\Employee\Status;
use MoChat\App\WorkContact\Contract\ContactFieldPivotContract;
use MoChat\App\WorkContact\Contract\WorkContactContract;
use MoChat\App\WorkContact\Contract\WorkContactEmployeeContract;
use MoChat\App\WorkContact\Contract\WorkContactRoomContract;
use MoChat\App\WorkContact\Contract\WorkContactTagContract;
use MoChat\App\WorkContact\Contract\WorkContactTagPivotContract;
use MoChat\App\WorkDepartment\Contract\WorkDepartmentContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeContract;
use MoChat\App\WorkEmployee\Contract\WorkEmployeeDepartmentContract;
use MoChat\App\WorkRoom\Contract\WorkRoomContract;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Plugin\ContactStage\Contract\ContactStageContract;

/**
 * 排除重复客户数量.
 *
 * Class ContactDistinctCount
 * @Controller
 */
class ContactDistinctCount extends AbstractAction
{
    /**
     * @Inject
     * @var WorkEmployeeDepartmentContract
     */
    protected $workEmployeeDepartmentService;

    /**
     * @Inject
     * @var WorkDepartmentContract
     */
    protected $workDepartmentService;

    /**
     * @Inject
     * @var ContactStageContract
     */
    protected $contactStageService;

    /**
     * 客户表.
     * @Inject
     * @var WorkContactContract
     */
    private $workContactService;

    /**
     * 员工 - 客户关联.
     * @Inject
     * @var WorkContactEmployeeContract
     */
    private $workContactEmployeeService;

    /**
     * 标签.
     * @Inject
     * @var WorkContactTagContract
     */
    private $workContactTagService;

    /**
     * 客户 - 标签关联.
     * @Inject
     * @var WorkContactTagPivotContract
     */
    private $workContactTagPivotService;

    /**
     * 用户画像.
     * @Inject
     * @var ContactFieldPivotContract
     */
    private $contactFieldPivotService;

    /**
     * 客户群.
     * @Inject
     * @var WorkRoomContract
     */
    private $workRoomService;

    /**
     * 客户 - 群关联.
     * @Inject
     * @var WorkContactRoomContract
     */
    private $workContactRoomService;

    /**
     * 员工.
     * @Inject
     * @var WorkEmployeeContract
     */
    private $workEmployeeService;

    /**
     * 企业表.
     * @Inject
     * @var CorpContract
     */
    private $corpService;

    /**
     * @Middlewares({
     *     @Middleware(DashboardAuthMiddleware::class),
     *     @Middleware(PermissionMiddleware::class)
     * })
     * @RequestMapping(path="/dashboard/workContact/contactDistinctCount", methods="GET")
     */
    public function handle()
    {
        $corpId = user()['corpIds'];
        if (count($corpId) != 1) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '请先选择企业');
        }

        // 接收参数
        $params = $this->request->inputs(
            [
                'keyWords', 'remark', 'fieldId', 'fieldType', 'fieldValue', 'gender', 'addWay', 'roomId', 'groupNum',
                'employeeId', 'startTime', 'endTime', 'businessNo', 'page', 'perPage', 'tags', 'lossStatus', 'type',
            ],
            [
                'page' => 1, 'perPage' => 20, 'type' => 1,
            ]
        );

        return ['total' => $this->getContact($params)];
    }

    private function getContact(array $params): int
    {
        $corpId = user()['corpIds'][0];
        // 企业id
        $search['corpId'] = $corpId;

        // 数据权限 0-全企业，1-本部门数据，2-当前登录人
        if (user()['dataPermission'] != 0) {
            // 员工id
            $search['employeeIds'] = array_unique(user()['deptEmployeeIds']);
        }

        // 状态为正常
        $search['status'] = Status::NORMAL;

        // 备注搜索
        if (! empty($params['remark'])) {
            $search['remark'] = $params['remark'];
        }
        // 客户来源搜索
        if (is_numeric($params['addWay'])) {
            $search['addWay'] = (int) $params['addWay'];
        }
        // 添加时间搜索
        if (! empty($params['startTime'])) {
            $search['startTime'] = $params['startTime'];
        }
        if (! empty($params['endTime'])) {
            $search['endTime'] = $params['endTime'];
        }
        // 流失状态搜索
        if (! empty($params['lossStatus'])) {
            $search['status'] = (int) $params['lossStatus'];
        }
        // 部门成员搜索
        if (! empty($params['employeeId'])) {
            if ($params['employeeId'] == '空') {
                // 查询不出数据 的标识
                $where['flag'] = 1;
            }
            $employeeIds = explode(',', $params['employeeId']);

            if (isset($where['employeeId'])) {
                $where['employeeId'] = array_intersect($where['employeeId'], $employeeIds);
            } else {
                $where['employeeId'] = $employeeIds;
            }
        }

        $contactEmployee = $this->workContactEmployeeService->getWorkContactEmployeesBySearch($search, ['contact_id']);
        if (empty($contactEmployee)) {
            return 0;
        }
        $contactIds = array_unique(array_column($contactEmployee, 'contactId'));

        // 关键词搜索
        if (! empty($params['keyWords']) || ! empty($params['businessNo']) || ! empty($params['gender'])) {
            $data['corpId'] = $corpId;
            $data['ids'] = $contactIds;
            $data['businessNo'] = $params['businessNo'] ?? '';
            $data['name'] = $params['keyWords'] ?? '';
            $data['gender'] = empty($params['gender']) ? '' : (int) $params['gender'];

            $contact = $this->workContactService->getWorkContactsByCorpIdSearch($data, ['id']);
            if (empty($contact)) {
                return 0;
            }
            $contactIds = array_column($contact, 'id');
        }

        // 用户画像搜索
        if (is_numeric($params['fieldId']) && $params['fieldId'] != 0) {
            // 查询满足用户画像值的用户id
            $pivot = $this->contactFieldPivotService
                ->getContactFieldPivotsByFieldIdValue($params['fieldId'], $params['fieldValue'], ['contact_id']);
            if (empty($pivot)) {
                return 0;
            }
            $pivotContactIds = array_column($pivot, 'contactId');
            // 取交集
            $contactIds = array_intersect($contactIds, $pivotContactIds);
        }
        // 企业标签搜索
        if (! empty($params['tags']) && $params['tags'] !== '{}') {
            $params['tags'] = Json::decode($params['tags']);
            // 查询在标签里的客户id（1：以下标签满足其中之一，2：以下标签同时满足，3无任何标签）
            if (in_array((int) $params['tags']['type'], [1, 2])) {
                $tagPivot = $this->workContactTagPivotService->getWorkContactTagPivotsByContactTagIdsType($params['tags']['tagIds'], (int) $params['tags']['type'], [], ['contact_id']);
                if (! empty($tagPivot)) {
                    $contactIds = array_unique(array_column($tagPivot, 'contactId'));
                    if (isset($where['contactId'])) {
                        // 取交集
                        $where['contactId'] = array_intersect($where['contactId'], $contactIds);
                    } else {
                        $where['contactId'] = array_merge($contactIds);
                    }
                    $ids = $this->getContactEmployeeIds($contactIds, $params['tags']['tagIds']);
                    empty($ids) || $where['id'] = $ids;
                } else {
                    // 查询不出数据的标识
                    return 0;
                }
            }
            if ((int) $params['tags']['type'] === 3) {
                $contacts = $this->workContactService->getWorkContactsByCorpId(user()['corpIds'][0], ['id']);
                $tagPivot = $this->workContactTagPivotService->getWorkContactTagPivotsByContactTagIdsType($params['tags']['tagIds'], 3, array_column($contacts, 'id'), ['contact_id']);
                if (! empty($tagPivot)) {
                    $contactIds = array_unique(array_column($tagPivot, 'contactId'));
                    if (isset($where['contactId'])) {
                        // 取差集
                        $where['contactId'] = array_diff($where['contactId'], $contactIds);
                    } else {
                        $where['contactId'] = array_column($contacts, 'id');
                        // 取差集
                        $where['contactId'] = array_diff($where['contactId'], $contactIds);
                    }
                } else {
                    // 查询不出数据的标识
                    return 0;
                }
            }
        }
        // 群聊搜索
        if (! empty($params['roomId'])) {
            $roomIds = explode(',', $params['roomId']);
            // 查询在群聊里的客户id
            $roomInfo = $this->workContactRoomService->getWorkContactRoomsByRoomIds($roomIds, ['contact_id']);
            if (empty($roomInfo)) {
                return 0;
            }
            $roomContactIds = array_unique(array_column($roomInfo, 'contactId'));
            // 取交集
            $contactIds = array_intersect($contactIds, $roomContactIds);
        }

        return count($contactIds);
    }

    private function getContactEmployeeIds(array $contactIds, array $tagIds): array
    {
        $contactEmployees = $this->workContactEmployeeService->getWorkContactEmployeesByContactIds($contactIds, ['id', 'employee_id', 'contact_id']);
        foreach ($contactEmployees as $key => $val) {
            $contactTags = $this->workContactTagPivotService->getWorkContactTagPivotsByContactIdsEmployeeIdsTagIds([$val['contactId']], [$val['employeeId']], $tagIds, 1);
            if (empty($contactTags)) {
                unset($contactEmployees[$key]);
            }
        }
        if (empty($contactEmployees)) {
            return [];
        }
        return array_column($contactEmployees, 'id');
    }
}
